﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using RpcHelper.Http;

namespace RpcHelper
{
    public class HttpResponse
    {
        private readonly HttpWebResponse _Response;
        internal HttpResponse(HttpWebResponse response)
        {
            this._Response = response;
        }
        public WebHeaderCollection Headers => this._Response.Headers;
        public CookieCollection Cookie => this._Response.Cookies;
        public long ContentLength => this._Response.ContentLength;

        public string GetExtension()
        {
            return Helper.GetFileType(this._Response);
        }


    }
    public enum DownProgress
    {
        开始 = 0,
        下载中 = 1,
        结束 = 2
    }
    public delegate void ReadStream(byte[] stream, int size, DownProgress progress, HttpResponse response);
    public class HttpTools
    {
        private const string _DefImgFormat = ".jpg";
        static HttpTools()
        {
            System.Net.ServicePointManager.DefaultConnectionLimit = int.MaxValue;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(_CheckValidationResult);
        }
        public static void SetSecurityProtocolType(SecurityProtocolType type)
        {
            ServicePointManager.SecurityProtocol = type;
        }
        private static bool _CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受  
        }
        private static HttpWebRequest _GetRequest(Uri uri, string post, HttpRequestSet reqSet)
        {
            if (post.IsNull())
            {
                return _CreateRequest(uri, reqSet, "GET");
            }
            return _GetRequest(uri, reqSet.RequestEncoding.GetBytes(post), reqSet);
        }
        private static HttpWebRequest _CreateRequest(Uri uri, HttpRequestSet reqSet, string method)
        {
            HttpWebRequest _Request = (HttpWebRequest)HttpWebRequest.Create(uri);
            _Request.Expect = null;
            _Request.Accept = reqSet.Accept;
            _Request.Timeout = reqSet.Timeout;
            _Request.Host = uri.Host;
            _Request.ReadWriteTimeout = reqSet.ReadWriteTimeout;
            _Request.ContinueTimeout = reqSet.ContinueTimeout;
            _Request.UserAgent = reqSet.UserAgent;
            _Request.ContentType = reqSet.ContentType;
            _Request.KeepAlive = false;
            _Request.SendChunked = reqSet.SendChunked;
            _Request.Referer = reqSet.Referer;
            _Request.ProtocolVersion = reqSet.ProtocolVersion;
            _Request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
            _Request.Method = reqSet.SubmitMethod.IsNull() ? method : reqSet.SubmitMethod;
            if (uri.Scheme == "https")
            {
                _Request.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(_CheckValidationResult);
                if (reqSet.HttpsCert != null)
                {
                    CertInfo cert = reqSet.HttpsCert;
                    _Request.ClientCertificates = new X509CertificateCollection();
                    X509Certificate2 obj = new X509Certificate2(cert.CertPath, cert.CertPwd);
                    _Request.ClientCertificates.Add(obj);
                }
                ServicePointManager.SecurityProtocol = reqSet.SecurityProtocolType;
            }
            if (reqSet.HeadList != null)
            {
                foreach (KeyValuePair<string, string> a in reqSet.HeadList)
                {
                    _Request.Headers.Add(string.Format("{0}:{1}", a.Key, a.Value));
                }
            }
            if (reqSet.Cookies != null)
            {
                _Request.CookieContainer = new CookieContainer();
                foreach (KeyValuePair<string, string> a in reqSet.Cookies)
                {
                    _Request.CookieContainer.Add(new Cookie(a.Key, a.Value, "/", uri.Authority));
                }
            }

            return _Request;
        }
        private static HttpWebRequest _GetRequest(Uri uri, byte[] post, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = _CreateRequest(uri, reqSet, "POST");
            _Request.ContentLength = post.Length;
            using (Stream stream = _Request.GetRequestStream())
            {
                stream.Write(post, 0, post.Length);
            }
            return _Request;
        }

        #region 读取流的方法
        private static void _ReadStream(Stream stream, HttpResponse response, ReadStream action, int size)
        {
            using (MemoryStream ms = new MemoryStream(size))
            {
                int read = 0;
                while (true)
                {
                    read = stream.ReadByte();
                    if (read == -1)
                    {
                        action(ms.ToArray(), (int)ms.Length, DownProgress.结束, response);
                        return;
                    }
                    ms.WriteByte((byte)read);
                    if (ms.Length == size)
                    {
                        action(ms.ToArray(), size, DownProgress.下载中, response);
                        ms.SetLength(0);
                    }
                }
            }
        }
        private static void _ReadStream(Stream source, HttpResponse response, ReadStream action, long len, int size = 1024)
        {
            if (len == -1)
            {
                _ReadStream(source, response, action, size);
                return;
            }
            if (size < len)
            {
                size = (int)len;
            }
            long read = 0;
            long max = len - size;
            byte[] myByte = new byte[size];
            int num;
            do
            {
                num = source.Read(myByte, 0, size);
                if (num > 0)
                {
                    read += num;
                    if (read == len)
                    {
                        action(myByte, num, DownProgress.结束, response);
                        break;
                    }
                    action(myByte, num, DownProgress.下载中, response);
                    if (read > max)
                    {
                        size = (int)(len - read);
                        myByte = new byte[size];
                    }
                }
            } while (true);
        }
        public static byte[] ReadStream(Stream stream)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                int read = 0;
                while (true)
                {
                    read = stream.ReadByte();
                    if (read == -1)
                    {
                        return ms.GetBuffer();
                    }
                    ms.WriteByte((byte)read);
                }
            }
        }
        public static void SaveFileStream(Stream stream, string path, long len, int size = 1024)
        {
            if (size < len)
            {
                size = (int)len;
            }
            long index = 0;
            long max = len - size;
            byte[] myByte = new byte[size];
            FileInfo file = new FileInfo(path);
            if (!file.Directory.Exists)
            {
                file.Directory.Create();
            }
            using (FileStream ms = file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Delete))
            {
                ms.Position = 0;
                do
                {
                    int num = stream.Read(myByte, 0, size);
                    if (num > 0)
                    {
                        ms.Write(myByte, 0, num);
                        index += num;
                        if (index > max && index != len)
                        {
                            size = (int)(len - index);
                            myByte = new byte[size];
                        }
                    }
                } while (index != len);
                ms.Flush();
                ms.Close();
            }
        }
        public static byte[] ReadStream(Stream SourceStream, long slen, int size = 1024)
        {
            if (slen == -1)
            {
                return ReadStream(SourceStream);
            }
            int len = (int)slen;
            if (size < len)
            {
                size = len;
            }
            int index = 0;
            int max = len - size;
            byte[] myByte = new byte[size];
            using (MemoryStream stream = new MemoryStream(len))
            {
                stream.Position = 0;
                do
                {
                    int num = SourceStream.Read(myByte, 0, size);
                    if (num > 0)
                    {
                        stream.Write(myByte, 0, num);
                        index += num;
                        if (index > max && index != len)
                        {
                            size = len - index;
                            myByte = new byte[size];
                        }
                    }
                } while (index != len);
                return stream.ToArray();
            }
        }
        #endregion
        private static void _ThorwException(Uri uri, string post, byte[] bytes, HttpStatusCode status, HttpRequestSet reqSet)
        {
            string res = bytes != null ? reqSet.ResponseEncoding.GetString(bytes) : string.Empty;
            throw new ErrorException("http.request.fail", new Dictionary<string, string> {
                                        { "StatusCode",((int)status).ToString()},
                                        { "Uri",uri.AbsoluteUri },
                                        { "Post",post},
                                        { "Result",res}
                                });
        }
        private static void _ThorwException(Uri uri, byte[] bytes, HttpStatusCode status, HttpRequestSet reqSet)
        {
            string res = bytes != null ? reqSet.ResponseEncoding.GetString(bytes) : string.Empty;
            throw new ErrorException("http.request.fail", new Dictionary<string, string> {
                                        { "StatusCode",((int)status).ToString()},
                                        { "Uri",uri.AbsoluteUri },
                                        { "Result",res}
                                });
        }

        public static string HttpPost(Uri uri, string post, HttpRequestSet reqSet)
        {
            byte[] bytes = HttpPostRequest(uri, post, reqSet, out HttpStatusCode code);
            if (code != HttpStatusCode.OK)
            {
                _ThorwException(uri, post, bytes, code, reqSet);
            }
            return reqSet.ResponseEncoding.GetString(bytes);
        }
        public static string HttpGet(Uri uri, HttpRequestSet reqSet)
        {
            byte[] bytes = HttpGetRequest(uri, reqSet, out HttpStatusCode code);
            if (code != HttpStatusCode.OK)
            {
                _ThorwException(uri, bytes, code, reqSet);
            }
            return reqSet.ResponseEncoding.GetString(bytes);
        }
        public static byte[] HttpPostRequest(Uri uri, string post, HttpRequestSet reqSet)
        {
            byte[] bytes = HttpGetRequest(uri, reqSet, out HttpStatusCode code);
            if (code != HttpStatusCode.OK)
            {
                _ThorwException(uri, post, bytes, code, reqSet);
            }
            return bytes;
        }
        public static HttpStreamRes GetStream(Uri uri, string post, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            HttpStreamRes res;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    res = new HttpStreamRes
                    {
                        StatusCode = response.StatusCode,
                        HeadList = new KeValue[response.Headers.Count],
                        ContentType = response.ContentType
                    };
                    int i = 0;
                    foreach (string name in response.Headers)
                    {
                        res.HeadList[i++] = new KeValue
                        {
                            Name = name,
                            Value = response.Headers[name]
                        };
                    }
                    if (response.Cookies.Count > 0)
                    {
                        res.Cookies = new KeValue[response.Cookies.Count];
                        i = 0;
                        foreach (Cookie cookie in response.Cookies)
                        {
                            res.Cookies[i++] = new KeValue
                            {
                                Name = cookie.Name,
                                Value = cookie.Value
                            };
                        }
                    }
                    if (response.StatusCode != HttpStatusCode.NoContent)
                    {
                        using (Stream stream = response.GetResponseStream())
                        {
                            res.Stream = ReadStream(stream, response.ContentLength);
                        }
                    }
                    response.Close();
                    response.Dispose();
                }
                return res;
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            finally
            {
                if (_Request != null)
                {
                    _Request.Abort();
                }
            }
        }
        public static HttpStatusCode HttpPostVoid(Uri uri, string post, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    HttpStatusCode status = response.StatusCode;
                    response.Close();
                    return status;
                }
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            finally
            {
                _Request?.Abort();
            }
        }
        public static byte[] HttpPostRequest(Uri uri, string post, HttpRequestSet reqSet, out HttpStatusCode status)
        {
            HttpWebRequest _Request = null;
            byte[] bytes = null;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    status = response.StatusCode;
                    if (status != HttpStatusCode.NoContent)
                    {
                        using (Stream stream = response.GetResponseStream())
                        {
                            bytes = ReadStream(stream, response.ContentLength);
                        }
                    }
                    response.Close();
                }
                return bytes;
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            finally
            {
                _Request?.Abort();
            }
        }
        public static byte[] HttpGetRequest(Uri uri, HttpRequestSet reqSet, out HttpStatusCode status)
        {
            HttpWebRequest _Request = null;
            byte[] bytes = null; ;
            try
            {
                _Request = _CreateRequest(uri, reqSet, "GET");
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    status = response.StatusCode;
                    if (status != HttpStatusCode.NoContent)
                    {
                        using (Stream stream = response.GetResponseStream())
                        {
                            bytes = ReadStream(stream, response.ContentLength);
                        }
                    }
                    response.Close();
                }
                return bytes;
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri}
                                });
            }
            finally
            {
                if (_Request != null)
                {
                    _Request.Abort();
                }
            }
        }
        public static HttpStatusCode SubmitByte(Uri uri, byte[] post, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                HttpStatusCode code = HttpStatusCode.OK;
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    code = response.StatusCode;
                    response.Close();
                }
                return code;
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "bytes",Convert.ToBase64String(post)}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri},
                                      { "bytes",Convert.ToBase64String(post)}
                                });
            }
            finally
            {
                if (_Request != null)
                {
                    _Request.Abort();
                }
            }
        }

        /// <summary>
        /// 获取请求头中的文件名
        /// </summary>
        /// <param name="head"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private static bool _GetHeaderFileName(string head, out string fileName)
        {
            string[] temp = head.ToLower().Split(';');
            head = Array.Find(temp, a => a.Trim().StartsWith("filename="));
            if (head != null)
            {
                fileName = head.Replace("filename=", string.Empty).Replace("\"", string.Empty).Trim();
                return true;
            }
            fileName = null;
            return false;
        }
        private static string _GetFileSavePath(Uri uri, HttpWebResponse response, string savePath, HttpRequestSet reqSet)
        {
            string extension = null;
            if (!string.IsNullOrEmpty(response.Headers.Get("Content-Disposition")))
            {
                if (_GetHeaderFileName(response.Headers.Get("Content-Disposition"), out string name))
                {
                    extension = Path.GetExtension(name);
                }
                else if (Path.HasExtension(savePath))
                {
                    extension = Path.GetExtension(name);
                }
            }
            else if (Path.HasExtension(savePath))
            {
                extension = Path.GetExtension(savePath);
            }
            if (reqSet.FileSave != null)
            {
                return reqSet.FileSave.Invoke(uri, savePath, extension);
            }
            else if (!string.IsNullOrEmpty(extension))
            {
                return !reqSet.IsResetFileName
                        ? Path.ChangeExtension(savePath, extension)
                        : Path.Combine(Path.GetDirectoryName(savePath), string.Format("{0}{1}", Guid.NewGuid().ToString("n"), extension));
            }
            else
            {
                throw new ErrorException("http.file.extension.null");
            }
        }

        public static HttpStatusCode DownFile(Uri uri, string post, ReadStream read, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        return response.StatusCode;
                    }
                    HttpResponse res = new HttpResponse(response);
                    using (Stream stream = response.GetResponseStream())
                    {
                        read(null, 0, DownProgress.开始, res);
                        _ReadStream(stream, res, read, response.ContentLength, 1024);
                        response.Close();
                        response.Dispose();
                    }
                    return HttpStatusCode.OK;
                }
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                         { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                      { "uri",uri.AbsoluteUri},
                                      { "post",post}
                                });
            }
            finally
            {
                _Request?.Abort();
            }
        }
        public static HttpStatusCode DownFile(Uri uri, string post, ref string savePath, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        return response.StatusCode;
                    }
                    savePath = _GetFileSavePath(uri, response, savePath, reqSet);

                    using (Stream stream = response.GetResponseStream())
                    {
                        SaveFileStream(stream, savePath, response.ContentLength);
                        response.Close();
                        response.Dispose();
                    }
                    return HttpStatusCode.OK;
                }
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                         { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                      { "uri",uri.AbsoluteUri},
                                      { "post",post}
                                });
            }
            finally
            {
                _Request?.Abort();
            }
        }

        public static byte[] UploadFile(Uri uri, string post, string filePath, HttpRequestSet reqSet)
        {
            FileInfo file = new FileInfo(filePath);
            if (!file.Exists)
            {
                throw new ErrorException("http.file.not.find");
            }
            HttpWebRequest _Request = null;
            try
            {
                string boundary = "----" + DateTime.Now.Ticks.ToString("x");
                reqSet.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
                _Request = _CreateRequest(uri, reqSet, "POST");
                using (Stream stream = _Request.GetRequestStream())
                {
                    string line = null;
                    byte[] myByte = null;
                    if (!string.IsNullOrEmpty(post))
                    {
                        line = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"description\"\r\n\r\n{1}\r\n", boundary, post);
                        myByte = reqSet.RequestEncoding.GetBytes(line);
                        stream.Write(myByte, 0, myByte.Length);
                    }
                    line = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"media\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, file.Name);
                    myByte = reqSet.RequestEncoding.GetBytes(line);
                    stream.Write(myByte, 0, myByte.Length);
                    using (FileStream fStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        myByte = new byte[1024];
                        int bytesRead = 0;
                        while ((bytesRead = fStream.Read(myByte, 0, myByte.Length)) != 0)
                        {
                            stream.Write(myByte, 0, bytesRead);
                        }
                    }
                    myByte = reqSet.RequestEncoding.GetBytes("\r\n--" + boundary + "--\r\n");
                    stream.Write(myByte, 0, myByte.Length);
                    stream.Flush();
                }
                byte[] resByte = null;
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        resByte = ReadStream(stream, response.ContentLength);
                    }
                    response.Close();
                    response.Dispose();
                }
                return resByte;
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri},
                                      { "post",post}
                                });
            }
            finally
            {
                if (_Request != null)
                {
                    _Request.Abort();
                }
            }
        }


        private static string _GetImgType(Uri uri, HttpWebResponse response, string savePath, HttpRequestSet reqSet)
        {
            string imgType = null;
            if (!string.IsNullOrEmpty(response.Headers.Get("Content-Disposition")))
            {
                if (_GetHeaderFileName(response.Headers.Get("Content-Disposition"), out string newName))
                {
                    imgType = Path.GetExtension(newName);
                }
            }
            if (string.IsNullOrEmpty(imgType) && !string.IsNullOrEmpty(response.ContentType))
            {
                imgType = Tools.GetImgExtension(response.ContentType);
            }
            if (string.IsNullOrEmpty(imgType))
            {
                imgType = Path.GetExtension(uri.LocalPath);
                if (string.IsNullOrEmpty(imgType) && Path.HasExtension(savePath))
                {
                    imgType = Path.GetExtension(savePath);
                }
            }
            if (string.IsNullOrEmpty(imgType) && reqSet.ImageExten != null)
            {
                imgType = reqSet.ImageExten.Invoke(uri, response);
            }
            if (string.IsNullOrEmpty(imgType))
            {
                imgType = _DefImgFormat;
            }
            return imgType;
        }
        private static void _InitImgSavePath(Uri uri, HttpWebResponse response, ref string savePath, HttpRequestSet reqSet)
        {
            string imgType = _GetImgType(uri, response, savePath, reqSet);
            if (reqSet.FileSave != null)
            {
                string path = reqSet.FileSave.Invoke(uri, savePath, imgType);
                savePath = string.IsNullOrEmpty(path)
                        ? Path.Combine(Path.GetDirectoryName(savePath), string.Format("{0}{1}", Guid.NewGuid().ToString("N"), imgType))
                        : path;
            }
            else
            {
                savePath = Path.HasExtension(savePath)
                        ? !reqSet.IsResetFileName
                                ? Path.ChangeExtension(savePath, imgType)
                                : Path.Combine(Path.GetDirectoryName(savePath), string.Format("{0}{1}", Guid.NewGuid().ToString("N"), imgType))
                        : Path.Combine(savePath, string.Format("{0}{1}", Guid.NewGuid().ToString("N"), imgType));
            }
        }
        public static HttpStatusCode DownImageFile(Uri uri, ref string savePath, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            try
            {
                _Request = _CreateRequest(uri, reqSet, "GET");
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        return response.StatusCode;
                    }
                    _InitImgSavePath(uri, response, ref savePath, reqSet);
                    using (Stream stream = response.GetResponseStream())
                    {
                        SaveFileStream(stream, savePath, response.ContentLength, 200);
                        response.Close();
                        response.Dispose();
                        return response.StatusCode;
                    }
                }
            }
            catch (WebException e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "savePath",savePath}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                        { "uri",uri.AbsoluteUri},
                                        { "savePath",savePath}
                                });
            }
            finally
            {
                if (_Request != null)
                {
                    _Request.Abort();
                }
            }
        }


        public static HttpResponseRes SendRequest(Uri uri, string post, HttpRequestSet reqSet)
        {
            HttpWebRequest _Request = null;
            try
            {
                _Request = _GetRequest(uri, post, reqSet);
                using (HttpWebResponse response = (HttpWebResponse)_Request.GetResponse())
                {
                    byte[] bytes = null;
                    HttpStatusCode status = HttpStatusCode.OK;
                    KeValue[] cookies = null;
                    using (Stream stream = response.GetResponseStream())
                    {
                        status = response.StatusCode;
                        if (status != HttpStatusCode.NoContent)
                        {
                            bytes = ReadStream(stream, response.ContentLength);
                        }
                        if (response.Cookies.Count > 0)
                        {
                            cookies = new KeValue[response.Cookies.Count];
                            int i = 0;
                            foreach (Cookie cookie in response.Cookies)
                            {
                                cookies[i++] = new KeValue
                                {
                                    Name = cookie.Name,
                                    Value = cookie.Value
                                };
                            }
                        }
                    }
                    response.Close();
                    return new HttpResponseRes(bytes,
                        cookies,
                        reqSet.RequestEncoding,
                        status);
                }
            }
            catch (WebException e)
            {
                string error = string.Concat("http.error.", (int)e.Status);
                throw new ErrorException(e, error, new Dictionary<string, string> {
                                        { "Status",e.Status.ToString()},
                                        { "uri",uri.AbsoluteUri},
                                        { "post",post}
                                });
            }
            catch (Exception e)
            {
                throw new ErrorException(e, new Dictionary<string, string> {
                                      { "uri",uri.AbsoluteUri},
                                      { "post",post}
                                });
            }
            finally
            {
                _Request?.Abort();
            }
        }

    }
}
